﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Utility.Math
{
	public static class RectEX
	{
		//shift
		public static Rect Shift (this Rect rect, Vector2 d)
		{
			return new Rect (rect.x + d.x, rect.y + d.y, rect.width, rect.height);
		}

		public static Rect Shift (this Rect rect, float x, float y)
		{
			return new Rect (rect.x + x, rect.y + y, rect.width, rect.height);
		}

		public static Rect ShiftLeft (this Rect rect, float value)
		{
			return new Rect (rect.x - value, rect.y, rect.width, rect.height);
		}

		public static Rect ShiftRight (this Rect rect, float value)
		{
			return new Rect (rect.x + value, rect.y, rect.width, rect.height);
		}

		public static Rect ShiftUp (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y + value, rect.width, rect.height);
		}

		public static Rect ShiftDown (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y - value, rect.width, rect.height);
		}

		//shift self
		public static Rect ShiftLeft (this Rect rect)
		{
			return new Rect (rect.x - rect.width, rect.y, rect.width, rect.height);
		}

		public static Rect ShiftRight (this Rect rect)
		{
			return new Rect (rect.x + rect.width, rect.y, rect.width, rect.height);
		}

		public static Rect ShiftUp (this Rect rect)
		{
			return new Rect (rect.x, rect.y + rect.height, rect.width, rect.height);
		}

		public static Rect ShiftDown (this Rect rect)
		{
			return new Rect (rect.x, rect.y - rect.height, rect.width, rect.height);
		}

		//shrink
		public static Rect Shrink (this Rect rect, float width, float height)
		{
			return new Rect (rect.x + width / 2, rect.y + height / 2, rect.width - width, rect.height - height);
		}

		public static Rect Shrink (this Rect rect, float left, float right, float up, float down)
		{
			return new Rect (rect.x + left, rect.y + down, rect.width - left - right, rect.height - up - down);
		}

		public static Rect Shrink (this Rect rect, RectOffset offset)
		{
			return new Rect (rect.x + offset.left, rect.y + offset.top, rect.width - offset.horizontal, rect.height - offset.vertical);
		}

		public static Rect ShrinkWidth (this Rect rect, float width)
		{
			return new Rect (rect.x + width / 2, rect.y, rect.width - width, rect.height);
		}

		public static Rect ShrinkWidth (this Rect rect, float left, float right)
		{
			return new Rect (rect.x + left, rect.y, rect.width - left - right, rect.height);
		}

		public static Rect ShrinkHeight (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.y + height / 2, rect.width, rect.height - height);
		}

		public static Rect ShrinkHeight (this Rect rect, float up, float down)
		{
			return new Rect (rect.x, rect.y + down, rect.width, rect.height - up - down);
		}

		public static Rect ShrinkRight (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y, rect.width - value, rect.height);
		}

		public static Rect ShrinkLeft (this Rect rect, float value)
		{
			return new Rect (rect.x + value, rect.y, rect.width - value, rect.height);
		}

		public static Rect ShrinkUp (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y, rect.width, rect.height - value);
		}

		public static Rect ShrinkDown (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y + value, rect.width, rect.height - value);
		}

		//expand
		public static Rect Expand (this Rect rect, float width, float height)
		{
			return new Rect (rect.x - width / 2, rect.y - height / 2, rect.width + width, rect.height + height);
		}

		public static Rect Expand (this Rect rect, float left, float right, float up, float down)
		{
			return new Rect (rect.x - left, rect.y - down, rect.width + left + right, rect.height + up + down);
		}

		public static Rect ExpandWidth (this Rect rect, float width)
		{
			return new Rect (rect.x - width / 2, rect.y, rect.width + width, rect.height);
		}

		public static Rect ExpandWidth (this Rect rect, float left, float right)
		{
			return new Rect (rect.x - left, rect.y, rect.width + left + right, rect.height);
		}

		public static Rect ExpandHeight (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.y - height / 2, rect.width, rect.height + height);
		}

		public static Rect ExpandHeight (this Rect rect, float up, float down)
		{
			return new Rect (rect.x, rect.y - down, rect.width, rect.height + up + down);
		}

		public static Rect ExpandRight (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y, rect.width + value, rect.height);
		}

		public static Rect ExpandLeft (this Rect rect, float value)
		{
			return new Rect (rect.x - value, rect.y, rect.width + value, rect.height);
		}

		public static Rect ExpandUp (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y, rect.width, rect.height + value);
		}

		public static Rect ExpandDown (this Rect rect, float value)
		{
			return new Rect (rect.x, rect.y - value, rect.width, rect.height + value);
		}

		//divide
		public static Rect Divide (this Rect rect, int x, int y)
		{
			x = x <= 0 ? 1 : x;
			y = y <= 0 ? 1 : y;
			return new Rect (rect.x, rect.y, rect.width / x, rect.height / y);
		}

		public static Rect DivideWidth (this Rect rect, int x = 2)
		{
			x = x <= 0 ? 1 : x;
			return new Rect (rect.x, rect.y, rect.width / x, rect.height);
		}

		public static Rect DivideWidth (this Rect rect, int x, int take)
		{
			x = x <= 0 ? 1 : x;
			take = take > x ? x : take;
			return new Rect (rect.x, rect.y, take * rect.width / x, rect.height);
		}

		public static Rect DivideHeight (this Rect rect, int y = 2)
		{
			y = y <= 0 ? 1 : y;
			return new Rect (rect.x, rect.y, rect.width, rect.height / y);
		}

		public static Rect DivideHeight (this Rect rect, int y, int take)
		{
			y = y <= 0 ? 1 : y;
			take = take > y ? y : take;
			return new Rect (rect.x, rect.y, rect.width, take * rect.height / y);
		}

		//dock
		public static Rect DockRight (this Rect rect, float width)
		{
			return new Rect (rect.xMax - width, rect.y, width, rect.height);
		}

		public static Rect DockLeft (this Rect rect, float width)
		{
			return new Rect (rect.x, rect.y, width, rect.height);
		}

		public static Rect DockUp (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.yMax - height, rect.width, height);
		}

		public static Rect DockDown (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.y, rect.width, height);
		}

		//resize
		public static Rect Resize (this Rect rect, float width, float height)
		{
			return new Rect (rect.x, rect.y, width, height);
		}

		public static Rect Resize (this Rect rect, Vector2 size)
		{
			return new Rect (rect.x, rect.y, size.x, size.y);
		}

		public static Rect ResizeWidth (this Rect rect, float width)
		{
			return new Rect (rect.x, rect.y, width, rect.height);
		}

		public static Rect ResizeHeight (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.y, rect.width, height);
		}

		public static Rect ResizeLeftTo (this Rect rect, float width)
		{
			return new Rect (rect.x - width + rect.width, rect.y, width, rect.height);
		}

		public static Rect ResizeRightTo (this Rect rect, float width)
		{
			return new Rect (rect.x, rect.y, width, rect.height);
		}

		public static Rect ResizeDownTo (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.y - height + rect.height, rect.width, height);
		}

		public static Rect ResizeUpTo (this Rect rect, float height)
		{
			return new Rect (rect.x, rect.y, rect.width, height);
		}

		//moveto
		public static Rect MoveTo (this Rect rect, float x, float y)
		{
			return new Rect (x, y, rect.width, rect.height);
		}

		public static Rect MoveTo (this Rect rect, Vector2 position)
		{
			return new Rect (position.x, position.y, rect.width, rect.height);
		}

		public static Rect MoveToX (this Rect rect, float x)
		{
			return new Rect (x, rect.y, rect.width, rect.height);
		}

		public static Rect MoveToY (this Rect rect, float y)
		{
			return new Rect (rect.x, y, rect.width, rect.height);
		}

		public static Rect MoveLeftTo (this Rect rect, float newVal)
		{
			if (newVal <= rect.xMax)
			{
				return new Rect (newVal, rect.y, rect.xMax - newVal, rect.height);
			}
			else
			{
				return new Rect (rect.xMax, rect.y, newVal - rect.xMax, rect.height);
			}
		}

		public static Rect MoveRightTo (this Rect rect, float newVal)
		{
			if (newVal >= rect.xMin)
			{
				return new Rect (rect.x, rect.y, newVal, rect.height);
			}
			else
			{
				return new Rect (newVal, rect.y, rect.x - newVal, rect.height);
			}
		}

		//move center to
		public static Rect MoveCenterTo (this Rect rect, float x, float y)
		{
			Vector2 d = new Vector2 (x, y) - rect.center;
			return new Rect (rect.x + d.x, rect.y + d.y, rect.width, rect.height);
		}

		public static Rect MoveCenterTo (this Rect rect, Vector2 center)
		{
			Vector2 d = center - rect.center;
			return new Rect (rect.x + d.x, rect.y + d.y, rect.width, rect.height);
		}


		//scale
		public static Rect Scale (this Rect rect, float scale)
		{
			return new Rect (rect.x, rect.y, rect.width * scale, rect.height * scale);
		}

		public static Rect Scale (this Rect rect, Vector2 scale)
		{
			return new Rect (rect.x, rect.y, rect.width * scale.x, rect.height * scale.y);
		}





		//normalized pos
		public static Vector2 GetNormalizedPosition (this Rect rect, Vector2 position)
		{
			var d = position - rect.min;
			return new Vector2 (d.x / rect.width, d.y / rect.height);
		}
	}
}